using System;
using System.Collections.Generic;
using System.Text;

namespace Enyo
{
	public class DataInformation<T> : DataInformation, IList<DataInformationProperty<T>>
	{
		/// <summary>
		/// The property's return type.
		/// </summary>
		public override Type Type
		{
			get
			{
				return typeof(T);
			}
		}

		public delegate string GetStringHandler(T value);
		GetStringHandler m_GetStringCallback;
		/// <summary>
		/// A callback to inject an alternate string for the type.
		/// </summary>
		public GetStringHandler GetStringCallback
		{
			get { return m_GetStringCallback; }
			set { m_GetStringCallback = value; }
		}

		public override string GetString(object value)
		{
			return this.GetString((T)value);
		}

		public virtual string GetString(T value)
		{
			if (value == null)
				return "<null>";
			else if (this.GetStringCallback != null)
				return this.GetStringCallback(value);
			else
				return value.ToString();
		}

		private List<DataInformationProperty<T>> m_Properties = new List<DataInformationProperty<T>>();

		protected List<DataInformationProperty<T>> Properties
		{
			get { return m_Properties; }
			set { m_Properties = value; }
		}

		#region IList<DataInformationProperty<T>> Members

		public int IndexOf(DataInformationProperty<T> item)
		{
			return this.Properties.IndexOf(item);
		}

		public void Insert(int index, DataInformationProperty<T> item)
		{
			this.Properties.Insert(index, item);
		}

		public override void RemoveAt(int index)
		{
			this.Properties.RemoveAt(index);
		}

		public DataInformationProperty<T> this[int index]
		{
			get
			{
				return this.Properties[index];
			}
			set
			{
				this.Properties[index] = value;
			}
		}

		#endregion

		#region ICollection<DataInformationProperty<T>> Members

		public void Add(DataInformationProperty<T> item)
		{
			this.Properties.Add(item);
		}

		public override void Clear()
		{
			this.Properties.Clear();
		}

		public bool Contains(DataInformationProperty<T> item)
		{
			return this.Properties.Contains(item);
		}

		public void CopyTo(DataInformationProperty<T>[] array, int arrayIndex)
		{
			this.Properties.CopyTo(array, arrayIndex);
		}

		public override int Count
		{
			get { return this.Properties.Count; }
		}

		public override bool IsReadOnly
		{
			get { return false; }
		}

		public bool Remove(DataInformationProperty<T> item)
		{
			return this.Properties.Remove(item);
		}

		#endregion

		#region IEnumerable<DataInformationProperty<T>> Members

		public new IEnumerator<DataInformationProperty<T>> GetEnumerator()
		{
			return this.Properties.GetEnumerator();
		}

		#endregion

		#region IEnumerable Members

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return this.Properties.GetEnumerator();
		}

		#endregion

		#region IList<DataInformationProperty>
		public override void Add(DataInformationProperty item)
		{
			this.Add((DataInformationProperty<T>)item);
		}

		public override bool Contains(DataInformationProperty item)
		{
			return this.Contains((DataInformationProperty<T>)item);
		}

		public override void CopyTo(DataInformationProperty[] array, int arrayIndex)
		{
			List<DataInformationProperty> list = new List<DataInformationProperty>();
			foreach (DataInformationProperty<T> item in this)
				list.Add(item);
			list.CopyTo(array, arrayIndex);
		}

		public override int IndexOf(DataInformationProperty item)
		{
			return this.IndexOf((DataInformationProperty<T>)item);
		}

		public override void Insert(int index, DataInformationProperty item)
		{
			this.Insert(index, (DataInformationProperty<T>)item);
		}

		public override bool Remove(DataInformationProperty item)
		{
			return this.Remove((DataInformationProperty<T>)item);
		}
		#endregion IList<DataInformationProperty>
	}

	public abstract class DataInformation : ICollection<DataInformationProperty>
	{
		/// <summary>
		/// The property's return type.
		/// </summary>
		public abstract Type Type
		{
			get;
		}

		public abstract string GetString(object value);

		#region IList<DataInformationProperty> Members

		public abstract int IndexOf(DataInformationProperty item);

		public abstract void Insert(int index, DataInformationProperty item);

		public abstract void RemoveAt(int index);

		#endregion

		#region ICollection<DataInformationProperty> Members

		public abstract void Add(DataInformationProperty item);

		public abstract void Clear();

		public abstract bool Contains(DataInformationProperty item);

		public abstract void CopyTo(DataInformationProperty[] array, int arrayIndex);

		public abstract int Count { get; }

		public abstract bool IsReadOnly { get; }

		public abstract bool Remove(DataInformationProperty item);

		#endregion

		#region IEnumerable Members

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return this.GetEnumerator();
		}

		#endregion

		#region IEnumerable<DataInformationProperty> Members

		public IEnumerator<DataInformationProperty> GetEnumerator()
		{
			throw new Exception("The method or operation is not implemented.");
		}

		#endregion
	}
}
